#pragma once

#include <atomic>
#include <cstdint>
#include <memory>
#include <string>
#include <unordered_map>
#include <semaphore.h>
#include <ctime>

namespace El {
namespace Base {

/**
 * @brief 基于共享内存的环形缓冲区实现
 *
 * 此实现针对一个写入者和多个读取者的场景进行了优化。
 * 通过共享内存实现跨进程通信，适用于多个进程需要高效读写大量数据的场景。
 * 使用无锁读取设计，允许多个读取者并行读取数据，同时保证单一写入者的高效写入。
 */
class SharedRingBuffer {
public:
    // 默认读者ID
    static constexpr uint32_t DEFAULT_READER_ID = 0;

    // 无效的读者ID
    static constexpr uint32_t INVALID_READER_ID = UINT32_MAX;

    // 创建共享环形缓冲区
    static std::shared_ptr<SharedRingBuffer> Create(const std::string &name, size_t size, bool isWriter);

    // 析构函数
    ~SharedRingBuffer();

    // 写入数据
    ssize_t Write(const void *data, size_t size);

    // 读取数据
    ssize_t Read(void *data, size_t size, uint32_t readerId = DEFAULT_READER_ID);

    // 获取可读数据大小
    size_t GetReadableSize(uint32_t readerId = DEFAULT_READER_ID) const;

    // 获取可写入空间大小
    size_t GetWritableSize() const;

    // 清空缓冲区（只有写入者可以调用）
    void Clear();

    // 等待新数据可用（超时参数，单位毫秒，0表示无限等待）
    bool WaitForData(uint32_t timeoutMs = 0, uint32_t readerId = DEFAULT_READER_ID);

    // 关闭共享环形缓冲区
    void Close();

    // 定期更新心跳
    void UpdateHeartbeat();

    // 检查写入者是否活跃
    bool IsWriterActive(uint32_t timeoutSeconds = 10);

    // 设置写入者模式（仅用于测试）
    void SetWriterMode(bool isWriter)
    {
        isWriter_ = isWriter;
    }

private:
    // 环形缓冲区头部结构
    struct RingBufferHeader {
        uint32_t magic;                          // 魔数，用于验证共享内存格式
        uint32_t bufferSize;                     // 缓冲区大小
        std::atomic<uint32_t> activeReaders;     // 活跃读者位图
        std::atomic<bool> isWriting;             // 是否正在写入
        std::atomic<uint64_t> writeCount;        // 写入计数，用于通知读者有新数据
        std::atomic<size_t> writePos;            // 写入位置
        std::atomic<size_t> minReadPos;          // 所有读者中最小的读取位置
        std::atomic<uint32_t> readerCount;       // 当前注册的读者数量
        std::atomic<uint32_t> nextReaderId;      // 下一个可用的读者ID
        std::atomic<uint64_t> writerHeartbeat;   // 写入者心跳
        std::atomic<size_t> readerPositions[32]; // 支持最多32个读者的读取位置
    };

    // 构造函数（私有）
    SharedRingBuffer();

    // 初始化
    bool Init(const std::string &name, size_t size, bool isWriter);

    // 注册新读者（如果是读者，则为自己注册）
    uint32_t RegisterReader();

    // 注销读者
    void UnregisterReader(uint32_t readerId);

    // 更新最小读位置（只有写入者调用）
    void UpdateMinReadPosition();

    // 获取读者的读取位置
    size_t GetReaderPosition(uint32_t readerId) const;

    // 设置读者的读取位置
    void SetReaderPosition(uint32_t readerId, size_t position);

    // 为每个读者生成唯一的信号量名称
    std::string GenerateReaderSemName(uint32_t readerId) const;

    // 创建或打开读者信号量
    bool CreateOrOpenReaderSemaphore(uint32_t readerId);

    // 关闭并清理读者信号量
    void CloseReaderSemaphore(uint32_t readerId);

    // 通知特定读者有新数据
    void NotifyReader(uint32_t readerId);

    // 通知所有读者有新数据
    void NotifyAllReaders();

private:
    int shmFd_;                // 共享内存文件描述符
    void *shmAddr_;            // 共享内存地址
    RingBufferHeader *header_; // 共享内存头部指针
    uint8_t *buffer_;          // 数据缓冲区指针
    size_t bufferSize_;        // 缓冲区大小
    std::string shmName_;      // 共享内存名称
    bool isWriter_;            // 是否是写入者
    uint32_t myReaderId_;      // 当前进程的读者ID（如果是读者）
    std::string baseSemName_;  // 基础信号量名称
    sem_t *readerSemaphore_;   // 当前读者的信号量指针
};

} // namespace Base
} // namespace El